const Koa = require("koa");
const Router = require("koa-router");
const fs = require("fs");
const path = require("path");

var cors = require("koa2-cors");

const koaBody = require("koa-body");
const staticFile = require("koa-static");
const send = require("koa-send");
const { createServer } = require("http");
const { Server } = require("socket.io");
const app = new Koa();
const DBUtils = require("./DBUtils");

const httpServer = createServer(app.callback());
const io = new Server(httpServer, {
  /* options */
});

const router = new Router();

const { uuid, getClientIP, formatTime } = require("../utils/utils");
const moment = require("moment");

const prefix = "/mallapi";

// 首页数据 先缓存起来
let homeGoods = null;

function wrapper(func) {
  return async function () {
    try {
      await func(...arguments);
    } catch (e) {
      console.error(e);
    }
  };
}

io.on("connection", function (socket) {
  console.log("连接建立");
  socket.emit("news", { hello: "world" });
  socket.on("my other event", function (data) {
    console.log(data);
  });
  socket.on("sendMsg", function (data) {
    console.log(data);
  });
});

app.use(
  cors({
    credentials: true,
    methods: ["GET", "PUT", "POST"],
  })
);
app.use(
  koaBody({
    multipart: true,
    formidable: {
      maxFileSize: 200 * 1024 * 1024, // 设置上传文件大小最大限制，默认2M
    },
  })
);

function responseSuccess(data) {
  return {
    code: 0,
    msg: "保存成功",
    data: data,
  };
}

function responseFaild(data) {
  return {
    code: 1,
    msg: data,
    data: null,
  };
}

router.post(
  prefix + "/uploadFile",
  wrapper(async (ctx, next) => {
    let res = await Qiniu.uploadFile(ctx);
    ctx.body = responseSuccess(res);
  })
);

router.get(
  prefix + "/file",
  wrapper(async (ctx) => {
    const id = ctx.query.id;
    const path = "static/" + uuid();
    ctx.attachment(path);
    await send(ctx, path);
  })
);

router.post(
  prefix + "/queryCate",
  wrapper(async (ctx) => {
    console.log(111);
    // 查询数据
    let {} = ctx.request.body;

    let r = await DBUtils.query("select * from cate", []);
    ctx.body = responseSuccess(r);
  })
);

router.get(
  prefix + "/index",
  wrapper(async (ctx) => {
    // 查询首页的数据
    if (homeGoods == null) {
      let {} = ctx.request.body;
      let bigcates = await DBUtils.query("select * from bigcate");

      let cates = await DBUtils.query(
        "select * from cate where ishome=1 order by rankno desc"
      );

      let r = await DBUtils.query(
        "select * from goods where status=1 and deleteFlag=0 and  (" +
          cates.map((item) => `cate='${item.id}'`).join(" or ") +
          ") order by rankno desc",
        []
      );

      bigcates.forEach((bc) => {
        bc.children = cates.filter((item) => item.pid == bc.id);
      });

      cates.forEach((cate) => {
        cate.list = r.filter((item) => item.cate == cate.id);
      });

      homeGoods = {
        tabs: bigcates,
      };
    }
    ctx.body = responseSuccess(homeGoods);
  })
);

router.post(
  prefix + "/login",
  wrapper(async (ctx) => {
    console.log("login");
    // 查询数据
    let { mobile, vcode } = ctx.request.body;
    let user = await DBUtils.queryOne("select * from user where mobile = ?", [
      mobile,
    ]);

    if (!user) {
      ctx.body = responseFaild("数据错误");
      return;
    }
    if (user.vcode !== vcode) {
      ctx.body = responseFaild("验证码不正确");
      return;
    }

    await DBUtils.query(
      "update user set status=1,logintime=? where mobile = ?",
      [formatTime(), mobile]
    );

    user = await DBUtils.queryOne("select * from user where mobile = ?", [
      mobile,
    ]);

    ctx.body = responseSuccess(user);
    return;
  })
);

router.post(
  prefix + "/cart/add",
  wrapper(async (ctx) => {
    console.log(111);
    // 查询数据
    let { goodsid, userid, num, specid, specname, specprice, specunit } =
      ctx.request.body;

    if (!goodsid) {
      ctx.body = responseFaild("数据错误");
      return;
    }

    let r;
    if (specid) {
      r = await DBUtils.queryOne(
        "select * from cart where goodsid=? and userid=? and specid=?",
        [goodsid, userid, specid]
      );
    } else {
      let specitems = await DBUtils.query(
        "select * from specitem where goodsid=?",
        [goodsid]
      );

      if (specitems.length > 0) {
        ctx.body = responseFaild("加入失败，请选择规格");
        return;
      }

      r = await DBUtils.queryOne(
        "select * from cart where goodsid=? and userid=?",
        [goodsid, userid]
      );
    }
    if (r) {
      if (num <= 0) {
        if (specid) {
          await DBUtils.query(
            "delete from cart where goodsid=? and userid=? and specid=?",
            [goodsid, userid, specid]
          );
        } else {
          await DBUtils.query("delete from cart where goodsid=? and userid=?", [
            goodsid,
            userid,
          ]);
        }
      } else {
        console.log("specid===", specid);
        if (specid) {
          await DBUtils.query(
            "update cart set num = ? ,addtime=? where goodsid=? and userid=? and specid=?",
            [num, formatTime(), goodsid, userid, specid]
          );
        } else {
          await DBUtils.query(
            "update cart set num = ? ,addtime=? where goodsid=? and userid=?",
            [num, formatTime(), goodsid, userid]
          );
        }
      }
    } else {
      await DBUtils.query(
        "insert into cart (goodsid,addtime,num,userid,specid,specname,specprice,specunit) values (?,?,?,?,?,?,?,?)",
        [
          goodsid,
          formatTime(),
          num,
          userid,
          specid,
          specname,
          specprice,
          specunit,
        ]
      );
    }
    ctx.body = responseSuccess("");
  })
);

router.post(
  prefix + "/cart/query",
  wrapper(async (ctx) => {
    // 查询数据
    let { userid } = ctx.request.body;

    let r = await DBUtils.query(
      "select t1.id,t1.title,t1.image,t1.images,t1.video,t1.price,t1.limitedstart,t1.limitedend,t1.limiteddiscount,t0.specprice,t0.num,t0.specid,t0.specname,t0.specprice,t0.specunit from cart t0 left join goods t1 on t0.goodsid=t1.id  where userid=?",
      [userid]
    );

    r.forEach((item) => {
      if (item) {
        if (item.specprice) {
          if (
            item.limitedstart &&
            item.limitedend &&
            moment() >= moment(item.limitedstart) &&
            moment() <= moment(item.limitedend)
          ) {
            item.price = Math.floor(
              (item.specprice * 1 * item.limiteddiscount) / 100
            );
          } else {
            item.price = item.specprice;
          }
        } else {
          if (
            item.limitedstart &&
            item.limitedend &&
            moment() >= moment(item.limitedstart) &&
            moment() <= moment(item.limitedend)
          ) {
            item.price = Math.floor(
              (item.specprice * 1 * item.limiteddiscount) / 100
            );
          } else {
            item.price = item.specprice;
          }
        }
      }
    });

    ctx.body = responseSuccess(r);
  })
);

router.post(
  prefix + "/getGoods",
  wrapper(async (ctx) => {
    // 查询数据
    let { id } = ctx.request.body;

    let r = await DBUtils.queryOne("select * from goods where id=?", [id]);
    let specitems = await DBUtils.query(
      "select * from specitem where goodsid=?",
      [id]
    );
    r.specitems = specitems;
    r.notice = "每天下午三点前下单，当天发货，江浙沪第二天到达";
    ctx.body = responseSuccess(r);
  })
);

router.post(
  prefix + "/queryGoods",
  wrapper(async (ctx) => {
    // 查询数据
    let { cate, searchKey } = ctx.request.body;

    console.log("searchKey", searchKey);

    let r = await DBUtils.query(
      "select * from goods where 1=1  " +
        (searchKey ? " and title like " + "'%" + searchKey + "%'" : "") +
        (cate
          ? " and cate=? and status=1 and deleteFlag=0 order by rankno desc"
          : " and status=1" + " and deleteFlag=0 order by rankno desc"),
      [cate]
    );
    ctx.body = responseSuccess(r);
  })
);

router.post(
  prefix + "/address/query",
  wrapper(async (ctx) => {
    let { userid } = ctx.request.body;
    let r = await DBUtils.query("select * from address where userid=?", [
      userid,
    ]);
    ctx.body = responseSuccess(r);
  })
);

router.post(
  prefix + "/orders/get",
  wrapper(async (ctx) => {
    let { id, status } = ctx.request.body;
    let res = await DBUtils.queryOne("select * from orders where id=?", [id]);

    let list = await DBUtils.query(
      "select t0.*,t1.id as goodsid,t1.image,t1.title from ordersitem t0 left join goods t1 on t0.goodsid=t1.id where ordersid=?",
      [id]
    );
    res.items = list;

    ctx.body = responseSuccess(res);
  })
);

router.post(
  prefix + "/address/query",
  wrapper(async (ctx) => {
    let { userid } = ctx.request.body;
    let r = await DBUtils.query("select * from address where userid=?", [
      userid,
    ]);
    ctx.body = responseSuccess(r);
  })
);

router.post(
  prefix + "/address/save",
  wrapper(async (ctx) => {
    // 查询数据
    let {
      id,
      userid,
      name,
      phone,
      province,
      address,
      city,
      county,
      isdefault,
    } = ctx.request.body;
    if (id) {
      await DBUtils.query(
        "update address set name = ?,phone=?,address=?,provice=?,city=?,createtime=?,isdefault=?,county=? where id=?",
        [
          name,
          phone,
          address,
          province,
          city,
          formatTime(),
          isdefault,
          county,
          id,
        ]
      );
    } else {
      let res = await DBUtils.query(
        "insert into address (userid,name, phone, province, address,city,county,createtime,isdefault) values(?,?,?,?,?,?,?,?,?)",
        [
          userid,
          name,
          phone,
          province,
          address,
          city,
          county,
          formatTime(),
          isdefault,
        ]
      );
      id = res.insertId;
    }

    let addr = await DBUtils.queryOne("select * from address where id=?", [id]);
    ctx.body = responseSuccess(addr);
  })
);

router.post(
  prefix + "/orders/query",
  wrapper(async (ctx) => {
    let { userid, status } = ctx.request.body;
    let res;
    if (status === "") {
      res = await DBUtils.query(
        "select * from orders where userid=? and deleteFlag=0 order by createtime desc",
        [userid]
      );
    } else {
      res = await DBUtils.query(
        "select * from orders where userid=? and status=? and deleteFlag=0 order by createtime desc",
        [userid, status]
      );
    }

    let list = await DBUtils.query(
      "select t0.*,t1.id as goodsid,t1.image,t1.title from ordersitem t0 left join goods t1 on t0.goodsid=t1.id where userid=?",
      [userid]
    );
    res.forEach((e) => {
      let items = list.filter((item) => item.ordersid == e.id);
      e.items = items;
    });

    ctx.body = responseSuccess(res);
  })
);

router.post(
  prefix + "/orders/pre",
  wrapper(async (ctx) => {
    let { goodsList, userid } = ctx.request.body;
    let price = 0;
    for (let i = 0; i < goodsList.length; i++) {
      let obj = goodsList[i];
      let { id, specid, title, num, specname } = obj;
      let goods = await DBUtils.queryOne(
        "select * from goods where id=? and deleteFlag=0",
        [id]
      );
      if (!goods) {
        ctx.body = responseFaild("商品" + title + "已经下架");
        return;
      }
      //单位价格
      let sprice = 0;
      if (specid) {
        console.log("specid", specid);
        // 是规格
        let specitem = await DBUtils.queryOne(
          "select * from specitem where id=?",
          [specid]
        );
        if (!specitem) {
          ctx.body = responseFaild(
            "商品" + title + ",规格" + specname + "已经删除，请删除后再购买"
          );
          return;
        }
        sprice = specitem.price;
      } else {
        sprice = goods.price;
      }

      getClientIP(ctx.request).then((res) => {
        console.log("ip===", res);
      });

      console.log(
        "goods.limitedstart",
        goods.limitedstart,
        goods.limitedend,
        goods.limiteddiscount
      );
      // 判断是不是秒杀
      if (
        goods.limitedstart &&
        goods.limitedend &&
        moment() >= moment(goods.limitedstart) &&
        moment() <= moment(goods.limitedend)
      ) {
        // 是在秒杀中的商品
        sprice = Math.floor((sprice * goods.limiteddiscount) / 100);
      }

      obj.unitprice = sprice;
      price = price + sprice * num;
    }
    // let price = goodsList.reduce((prev, next) => {

    // }, 0);
    // 验证商品
    for (let i = 0; i < goodsList.length; i++) {
      let goods = goodsList[i];
      let savegoods = await DBUtils.queryOne("select * from goods where id=?", [
        goods.id,
      ]);
      if (savegoods.status !== 1) {
        ctx.body = responseFaild("商品已经下架");
        return;
      }
    }

    console.log("price===", price);

    let res = await DBUtils.query(
      "insert into orders (userid,price,createtime,status) values(?,?,?,?)",
      [userid, price, formatTime(), 0]
    );
    let ordersid = res.insertId;
    for (let i = 0; i < goodsList.length; i++) {
      let goods = goodsList[i];
      await DBUtils.query(
        "insert into ordersitem (userid,goodsid,ordersid,num,price,specid,specname,specprice,specunit) values(?,?,?,?,?,?,?,?,?)",
        [
          userid,
          goods.id,
          ordersid,
          goods.num,
          goods.unitprice,
          goods.specid,
          goods.specname,
          goods.specprice,
          goods.specunit,
        ]
      );
    }

    ctx.body = responseSuccess(ordersid);
  })
);

// 更新用户信息
router.post(
  prefix + "/user/update",
  wrapper(async (ctx) => {
    console.log("update", ctx.request.body);
    let { id, name, phone, address, province, city, county } = ctx.request.body;
    await DBUtils.query(
      "update user set name=?,phone=?,address=?,province=?,city=?,county=? where id=?",
      [name, phone, address, province, city, county, id]
    );
    ctx.body = responseSuccess("保存成功");
  })
);

app.use(staticFile(path.join(__dirname)));

app.use(router.routes());

httpServer.listen(9102);
console.log("app started at port 9102...");

process.on("uncaughtException", function (err) {
  //打印出错误
  console.log("我的天出错了!!!");
  console.log(err);
  //打印出错误的调用栈方便调试
  console.log(err.stack);
});
